/*
 * @Author: soso
 * @Date: 2022-02-22 13:58:49
 * @LastEditTime: 2022-03-03 17:15:44
 * @LastEditors: Please set LastEditors
 * @Description: 命令处理
 * @FilePath: /gomeshsync/cfile/define.go
 */
package cfile

import (
	"gomeshsync/consts"
	"log"
	"math"

	"gitee.com/kimsoso/go-utils/bitmap"
)

const (
	BitAdd       = iota // 设置位
	BitRemove           // 移除位
	BitAddFull          // 全部设置
	BitRemoveAll        // 全部移除
)

const (
	BitStatFull   = iota //全位设置
	BitStatZero          //0位设置
	BitStatSetted        //已设置
)

const (
	IsSAME   = iota // 文件相同
	IsADD           // 文件新增
	IsUPDATE        // 文件更新
	IsDELETE        // 文件已删除
	IsRENAME        // 文件已删除
)

const (
	IsFile = iota //文件
	IsDir         //目录
)

// 命令
type MCommand struct {
	Ck         int    `yaml:"ck"`
	Cmd        int    `yaml:"cd"`
	Path       string `yaml:"pt"`
	ToPath     string `yaml:"tpt"`
	CreateTime int64  `yaml:"cT"`
	DoneTime   int64  `yaml:"dT"`
	Done       bool   `yaml:"d"`

	File *Cfile `yaml:"f"`
}

// 文件
type Cfile struct {
	FileMd5         string `yaml:"md5"`
	FilePath        string `yaml:"fp"`
	FileSize        int64  `yaml:"fs"`
	BlockSize       int64  `yaml:"bs"`
	FileMask        []byte `yaml:"fm"`
	CreateTime      string `yaml:"ct"`
	CreateTimeStamp int64  `yaml:"cts"`
	Checked         bool   `yaml:"chd"`
}

// 检查位置是否设置
func BitMapSetted(data []byte, num uint) bool {
	b := bitmap.NewEmptyBitMap()
	b.UnSerialize(data)
	return b.IsExist(num)
}

// 位图置位:
// num: 设置第几位
// mode: 0 add, 1 remove, 2 addfull, 3 removefull
func BitMapSet(data []byte, num uint, mode int) []byte {
	b := bitmap.NewEmptyBitMap()
	b.UnSerialize(data)

	switch mode {
	case 0:
		b.Add(num)
	case 1:
		b.Remove(num)
	case 2:
		b.AddFull()
	case 3:
		b.RemoveAll()
	default:
		panic("invalid input params")
	}

	return b.Serialize()
}

// 位图状态
func BitMapStat(data []byte) (bm *bitmap.BitMap, stat int) {
	bm = bitmap.NewEmptyBitMap()
	err := bm.UnSerialize(data)
	if err != nil {
		log.Println("data is:", data, "error is:", err)
		panic("bitmap UnSerialize error:")
	}

	if bm.IsFull() {
		stat = BitStatFull
	} else if bm.IsEmpty() {
		stat = BitStatZero
	} else {
		stat = BitStatSetted
	}
	return
}

//计算文件掩码
func CalFileMask(filesize int64, dim string) []byte {
	// 分割块数量
	count := uint32(math.Ceil(float64(filesize) / float64(consts.BLOCKSIZE)))

	if dim == "1" {
		return bitmap.NewBitMap(count).AddFull().Serialize()
	} else {
		return bitmap.NewBitMap(count).Serialize()
	}
}
